package pool
//
//import (
//	"gitee.com/fenleng/flyfisher/backend"
//	"sync"
//	"sync/atomic"
//	"time"
//
//	"gitee.com/fenleng/flyfisher/core/errors"
//	"gitee.com/fenleng/flyfisher/mysql"
//	"gitee.com/fenleng/flyfisher/core/sync2"
//	"gitee.com/fenleng/flyfisher/core/resource_polll"
//)
//
//const (
//	Up = iota
//	Down
//	ManualDown
//	Unknown
//
//	InitConnCount           = 16
//	DefaultMaxConnNum       = 1024
//	PingPeroid        int64 = 4
//)
//
//type DB struct {
//	sync.RWMutex
//
//	addr     string
//	user     string
//	password string
//	db       string
//	state    int32
//	//conns   sync2.AtomicBool
//	conns       *resource_polll.ResourcePool
//	//maxConnNum  int
//	//InitConnNum int
//	//idleConns   chan *Conn
//	//cacheConns  chan *Conn
//	//checkConn   *Conn
//	//lastPing    int64
//	//
//	//pushConnCount int64
//	//popConnCount  int64
//}
//
//func Open(addr string, user string, password string, dbName string, maxConnNum int) (*DB, error) {
//	var err error
//	db := new(DB)
//	db.addr = addr
//	db.user = user
//	db.password = password
//	db.db = dbName
//	db.conns=resource_polll.NewResourcePool(db.newConn,maxConnNum,maxConnNum,1*time.Second)
//	//if 0 < maxConnNum {
//	//	db.maxConnNum = maxConnNum
//	//	if db.maxConnNum < 16 {
//	//		db.InitConnNum = db.maxConnNum
//	//	} else {
//	//		db.InitConnNum = db.maxConnNum / 4
//	//	}
//	//} else {
//	//	db.maxConnNum = DefaultMaxConnNum
//	//	db.InitConnNum = InitConnCount
//	//}
//	////check connection
//	//db.checkConn, err = db.newConn()
//	//if err != nil {
//	//	db.Close()
//	//	return nil, err
//	//}
//	//
//	//db.idleConns = make(chan *Conn, db.maxConnNum)
//	//db.cacheConns = make(chan *Conn, db.maxConnNum)
//	atomic.StoreInt32(&(db.state), Unknown)
//
//	//for i := 0; i < db.maxConnNum; i++ {
//	//	if i < db.InitConnNum {
//	//		conn, err := db.newConn()
//	//
//	//		if err != nil {
//	//			db.Close()
//	//			return nil, err
//	//		}
//	//
//	//		db.cacheConns <- conn
//	//		atomic.AddInt64(&db.pushConnCount, 1)
//	//	} else {
//	//		conn := new(Conn)
//	//		db.idleConns <- conn
//	//		atomic.AddInt64(&db.pushConnCount, 1)
//	//	}
//	//}
//	//db.SetLastPing()
//
//	return db, nil
//}
//
//func (db *DB) Addr() string {
//	return db.addr
//}
//
//func (db *DB) State() string {
//	var state string
//	switch db.state {
//	case Up:
//		state = "up"
//	case Down, ManualDown:
//		state = "down"
//	case Unknown:
//		state = "unknow"
//	}
//	return state
//}
//
//func (db *DB) ConnCount() (int, int, int64, int64) {
//	db.RLock()
//	defer db.RUnlock()
//	return len(db.idleConns), len(db.cacheConns), db.pushConnCount, db.popConnCount
//}
//
//func (db *DB) Close() error {
//	db.Lock()
//	idleChannel := db.idleConns
//	cacheChannel := db.cacheConns
//	db.cacheConns = nil
//	db.idleConns = nil
//	db.Unlock()
//	if cacheChannel == nil || idleChannel == nil {
//		return nil
//	}
//
//	close(cacheChannel)
//	for conn := range cacheChannel {
//		db.closeConn(conn)
//	}
//	close(idleChannel)
//
//	return nil
//}
//
//func (db *DB) getConns() (chan *Conn, chan *Conn) {
//	db.RLock()
//	cacheConns := db.cacheConns
//	idleConns := db.idleConns
//	db.RUnlock()
//	return cacheConns, idleConns
//}
//
//func (db *DB) getCacheConns() chan *Conn {
//	db.RLock()
//	conns := db.cacheConns
//	db.RUnlock()
//	return conns
//}
//
//func (db *DB) getIdleConns() chan *Conn {
//	db.RLock()
//	conns := db.idleConns
//	db.RUnlock()
//	return conns
//}
//
//func (db *DB) Ping() error {
//	var err error
//	if db.checkConn == nil {
//		db.checkConn, err = db.newConn()
//		if err != nil {
//			if db.checkConn != nil {
//				db.checkConn.Close()
//				db.checkConn = nil
//			}
//			return err
//		}
//	}
//	err = db.checkConn.Ping()
//	if err != nil {
//		if db.checkConn != nil {
//			db.checkConn.Close()
//			db.checkConn = nil
//		}
//		return err
//	}
//	return nil
//}
//
//func (db *DB) newConn() (*backend.Conn, error) {
//	co := new(backend.Conn)
//
//	if err := co.Connect(db.addr, db.user, db.password, db.db); err != nil {
//		return nil, err
//	}
//
//	//co = time.Now().Unix()
//
//	return co, nil
//}
//
//func (db *DB) addIdleConn() {
//	conn := new(Conn)
//	select {
//	case db.idleConns <- conn:
//	default:
//		break
//	}
//}
//
//func (db *DB) closeConn(co *Conn) error {
//	atomic.AddInt64(&db.pushConnCount, 1)
//
//	if co != nil {
//		co.Close()
//		conns := db.getIdleConns()
//		if conns != nil {
//			select {
//			case conns <- co:
//				return nil
//			default:
//				return nil
//			}
//		}
//	} else {
//		db.addIdleConn()
//	}
//	return nil
//}
//
//func (db *DB) closeConnNotAdd(co *Conn) error {
//	if co != nil {
//		co.Close()
//		conns := db.getIdleConns()
//		if conns != nil {
//			select {
//			case conns <- co:
//				return nil
//			default:
//				return nil
//			}
//		}
//	} else {
//		db.addIdleConn()
//	}
//	return nil
//}
//
//func (db *DB) tryReuse(co *Conn) error {
//	var err error
//	//reuse Connection
//	if co.IsInTransaction() {
//		//we can not reuse a connection in transaction status
//		err = co.Rollback()
//		if err != nil {
//			return err
//		}
//	}
//
//	if !co.IsAutoCommit() {
//		//we can not  reuse a connection not in autocomit
//		_, err = co.exec("set autocommit = 1")
//		if err != nil {
//			return err
//		}
//	}
//
//	//connection may be set names early
//	//we must use default utf8
//	if co.GetCharset() != mysql.DEFAULT_CHARSET {
//		err = co.SetCharset(mysql.DEFAULT_CHARSET, mysql.DEFAULT_COLLATION_ID)
//		if err != nil {
//			return err
//		}
//	}
//
//	return nil
//}
//
//func (db *DB) PopConn() (*Conn, error) {
//	var co *Conn
//	var err error
//
//	cacheConns, idleConns := db.getConns()
//	if cacheConns == nil || idleConns == nil {
//		return nil, errors.ErrDatabaseClose
//	}
//	co = db.GetConnFromCache(cacheConns)
//	if co == nil {
//		co, err = db.GetConnFromIdle(cacheConns, idleConns)
//		if err != nil {
//			return nil, err
//		}
//	}
//
//	err = db.tryReuse(co)
//	if err != nil {
//		db.closeConn(co)
//		return nil, err
//	}
//
//	return co, nil
//}
//
//func (db *DB) GetConnFromCache(cacheConns chan *Conn) *Conn {
//	var co *Conn
//	var err error
//	for 0 < len(cacheConns) {
//		co = <-cacheConns
//		atomic.AddInt64(&db.popConnCount, 1)
//		if co != nil && PingPeroid < time.Now().Unix()-co.pushTimestamp {
//			err = co.Ping()
//			if err != nil {
//				db.closeConn(co)
//				co = nil
//			}
//		}
//		if co != nil {
//			break
//		}
//	}
//	return co
//}
//
//func (db *DB) GetConnFromIdle(cacheConns, idleConns chan *Conn) (*Conn, error) {
//	var co *Conn
//	var err error
//	select {
//	case co = <-idleConns:
//		atomic.AddInt64(&db.popConnCount, 1)
//		co, err := db.newConn()
//		if err != nil {
//			db.closeConn(co)
//			return nil, err
//		}
//		err = co.Ping()
//		if err != nil {
//			db.closeConn(co)
//			return nil, errors.ErrBadConn
//		}
//		return co, nil
//	case co = <-cacheConns:
//		atomic.AddInt64(&db.popConnCount, 1)
//		if co == nil {
//			return nil, errors.ErrConnIsNil
//		}
//		if co != nil && PingPeroid < time.Now().Unix()-co.pushTimestamp {
//			err = co.Ping()
//			if err != nil {
//				db.closeConn(co)
//				return nil, errors.ErrBadConn
//			}
//		}
//	}
//	return co, nil
//}
//
//func (db *DB) PushConn(co *Conn, err error) {
//	atomic.AddInt64(&db.pushConnCount, 1)
//	if co == nil {
//		db.addIdleConn()
//		return
//	}
//	conns := db.getCacheConns()
//	if conns == nil {
//		co.Close()
//		return
//	}
//	if err != nil {
//		db.closeConnNotAdd(co)
//		return
//	}
//	co.pushTimestamp = time.Now().Unix()
//	select {
//	case conns <- co:
//		return
//	default:
//		db.closeConnNotAdd(co)
//		return
//	}
//}
//
////type BackendConn struct {
////	*Conn
////	db *DB
////}
////
////func (p *BackendConn) Close() {
////	if p != nil && p.Conn != nil {
////		if p.Conn.pkgErr != nil {
////			p.db.closeConn(p.Conn)
////		} else {
////			p.db.PushConn(p.Conn, nil)
////		}
////		p.Conn = nil
////	}
////}
////
////func (db *DB) GetConn() (*BackendConn, error) {
////	c, err := db.PopConn()
////	if err != nil {
////		return nil, err
////	}
////	return &BackendConn{c, db}, nil
////}
////
////func (db *DB) SetLastPing() {
////	db.lastPing = time.Now().Unix()
////}
////
////func (db *DB) GetLastPing() int64 {
////	return db.lastPing
////}
